home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / os2 / octa209s.zip / octave-2.09 / libs / pnm / bmp.c < prev    next >
C/C++ Source or Header  |  1997-02-01  |  7KB  |  331 lines

  1. /*
  2. *******************************************************************************
  3. ** Codec for Windows and OS/2 bitmaps                                        **
  4. ** (c) 1997, Klaus Gebhardt                                                  **
  5. *******************************************************************************
  6. */
  7.  
  8. #include <stdlib.h>
  9. #include <stdio.h>
  10.  
  11. #include "bitio.h"
  12. #include "oct-img.h"
  13.  
  14. extern UINT PutByte   (FILE *, UCHAR);
  15. extern UINT PutLShort (FILE *, SHORT);
  16. extern UINT PutLLong  (FILE *, INT);
  17.  
  18. extern UINT GetByte   (FILE *, UCHAR *);
  19. extern UINT GetLShort (FILE *, SHORT *);
  20. extern UINT GetLLong  (FILE *, INT *);
  21.  
  22. extern SHORT MaxValtoBits (INT);
  23.  
  24. extern UCHAR **malloc_uchar_matrix (UINT, UINT);
  25. extern INT   **malloc_int_matrix   (UINT, UINT);
  26.  
  27.  
  28. static UINT BMP_offbits (INT class, SHORT bpp)
  29. {
  30.   if (bpp < 1)  return 0;
  31.  
  32.   switch (class)
  33.     {
  34.     case BMP_WIN:
  35.       return 54 + (1 << bpp) * 4;
  36.     case BMP_OS2:
  37.       return 26 + (1 << bpp) * 3;
  38.     default:
  39.       return 0;
  40.     }
  41. }
  42.  
  43.  
  44. static UINT BMP_lenfile (INT class, SHORT bpp, UINT x, UINT y)
  45. {
  46.   UINT bits;
  47.  
  48.   switch (class)
  49.     {
  50.     case BMP_WIN:
  51.       break;
  52.     case BMP_OS2:
  53.       break;
  54.     default:
  55.       return 0;
  56.     }
  57.  
  58.   bits = x * bpp;
  59.  
  60.   if ((bits % 32) != 0)  bits += (32 - (bits % 32));
  61.   if ((bits % 32) != 0)  return 0;
  62.  
  63.   return BMP_offbits (class, bpp) + y * (bits >> 3);
  64. }
  65.  
  66.  
  67. static UINT BMP_writergb (FILE *fp, INT class, UCHAR R, UCHAR G, UCHAR B)
  68. {
  69.   UINT nbyte = 0;
  70.  
  71.   switch (class)
  72.     {
  73.     case BMP_WIN:
  74.       nbyte += PutByte (fp, B);
  75.       nbyte += PutByte (fp, G);
  76.       nbyte += PutByte (fp, R);
  77.       nbyte += PutByte (fp, 0);
  78.       return nbyte;
  79.     case BMP_OS2:
  80.       nbyte += PutByte (fp, B);
  81.       nbyte += PutByte (fp, G);
  82.       nbyte += PutByte (fp, R);
  83.       return nbyte;
  84.     default:
  85.       return 0;
  86.     }
  87.  
  88.   return 0;
  89. }
  90.  
  91.  
  92. static UINT BMP_writergbtable (FILE *fp, INT class, SHORT bpp,
  93.                   INT colors, UCHAR *R, UCHAR *G, UCHAR *B)
  94. {
  95.   UINT nbyte = 0;
  96.   INT i, ncolors;
  97.  
  98.   for (i = 0; i < colors; i++)
  99.     nbyte += BMP_writergb (fp, class, R[i], G[i], B[i]);
  100.  
  101.   ncolors = (1 << bpp);
  102.  
  103.   for (; i < ncolors; i++)
  104.     nbyte += BMP_writergb (fp, class, 0, 0, 0);
  105.  
  106.   return nbyte;
  107. }
  108.  
  109.  
  110. static int BMP_writerow (FILE *fp, INT *row, UINT cx, SHORT bpp)
  111. {
  112.   BITSTREAM b;
  113.   UINT nbyte = 0, x;
  114.   int rc;
  115.  
  116.   if ((b = bitinit (fp, "w")) == (BITSTREAM) 0)  return -1;
  117.  
  118.   for (x = 0; x < cx; x++)
  119.     {
  120.       if ((rc = bitwrite (b, bpp, (UCHAR) row[x])) == -1)  return -1;
  121.       nbyte += rc;
  122.     }
  123.  
  124.   if ((nbyte += bitfini (b)) == -1)  return -1;
  125.  
  126.   while (nbyte % 4)
  127.     {
  128.       PutByte (fp, 0);
  129.       nbyte++;
  130.     }
  131.  
  132.   return nbyte;
  133. }
  134.  
  135.  
  136. static UINT BMP_writebits (FILE *fp, UINT cx, UINT cy, SHORT bpp, INT **pixels)
  137. {
  138.   UINT nbyte = 0, y;
  139.   int rc;
  140.  
  141.   if(bpp > 8)  return 0;
  142.  
  143.   for (y = cy; y > 0; y--)
  144.     {
  145.       if ((rc = BMP_writerow (fp, pixels[y-1], cx, bpp)) % 4)  return 0;
  146.       nbyte += rc;
  147.     }
  148.  
  149.   return nbyte;
  150. }
  151.  
  152.  
  153. BOOL BMP_Encode (FILE *fp, INT class, UINT x, UINT y, INT **pixels,
  154.         INT colors, UCHAR **cm)
  155. {
  156.   SHORT bpp;
  157.   UINT nbyte = 0;
  158.  
  159.   if (colors < 1)                             return -1;
  160.   if ((bpp = MaxValtoBits (colors - 1)) > 8)  return -1;
  161.  
  162.   switch(bpp)
  163.     {
  164.     case 2:
  165.     case 3:
  166.       bpp = 4;
  167.       break;
  168.     case 5:
  169.     case 6:
  170.     case 7:
  171.       bpp = 8;
  172.       break;
  173.     }
  174.  
  175.   nbyte += PutByte (fp, 'B');
  176.   nbyte += PutByte (fp, 'M');
  177.   nbyte += PutLLong (fp, BMP_lenfile (class, bpp, x, y));
  178.   nbyte += PutLShort (fp, 0);
  179.   nbyte += PutLShort (fp, 0);
  180.   nbyte += PutLLong (fp, BMP_offbits (class, bpp));
  181.  
  182.   switch (class)
  183.     {
  184.     case BMP_WIN:
  185.       nbyte += PutLLong (fp, 40);
  186.       nbyte += PutLLong (fp, x);
  187.       nbyte += PutLLong (fp, y);
  188.       nbyte += PutLShort (fp, 1);
  189.       nbyte += PutLShort (fp, bpp);
  190.       nbyte += PutLLong (fp, 0);
  191.       nbyte += PutLLong (fp, 0);
  192.       nbyte += PutLLong (fp, 0);
  193.       nbyte += PutLLong (fp, 0);
  194.       nbyte += PutLLong (fp, 0);
  195.       nbyte += PutLLong (fp, 0);
  196.       break;
  197.     case BMP_OS2:
  198.       nbyte += PutLLong (fp, 12);
  199.       nbyte += PutLShort (fp, x);
  200.       nbyte += PutLShort (fp, y);
  201.       nbyte += PutLShort (fp, 1);
  202.       nbyte += PutLShort (fp, bpp);
  203.       break;
  204.     default:
  205.       return -1;
  206.     }
  207.  
  208.   nbyte += BMP_writergbtable (fp, class, bpp, colors, cm[0], cm[1], cm[2]);
  209.  
  210.   if (nbyte != BMP_offbits (class, bpp))  return -1;
  211.  
  212.   nbyte += BMP_writebits (fp, x, y, bpp, pixels);
  213.   if (nbyte != BMP_lenfile (class, bpp, x, y))  return -1;
  214.  
  215.   return 0;
  216. }
  217.  
  218. static int BMP_readrow (FILE *fp, INT *row, UINT cx, SHORT bpp,
  219.             INT *col_min, INT *col_max)
  220. {
  221.   BITSTREAM b;
  222.   UINT nbyte = 0, x, c;
  223.   int rc;
  224.  
  225.   if ((b = bitinit (fp, "r")) == (BITSTREAM) 0)  return -1;
  226.  
  227.   for (x = 0; x < cx; x++)
  228.     {
  229.       if ((rc = bitread (b, bpp, &c)) == -1)  return -1;
  230.       nbyte += rc;
  231.       *col_min = min (*col_min, (INT) c);
  232.       *col_max = max (*col_max, (INT) c);
  233.       row[x] = (INT) c;
  234.     }
  235.  
  236.   if ((rc = bitfini (b)) == -1)  return -1;
  237.   nbyte += rc;
  238.  
  239.   while (nbyte % 4)
  240.     nbyte += SkipBytes (fp, 1);
  241.  
  242.   return nbyte;
  243. }
  244.  
  245. static UINT BMP_readbits (FILE *fp, UINT cx, UINT cy, SHORT bpp,
  246.               INT *col_min, INT *col_max, INT **pixels)
  247. {
  248.   UINT y, nbyte = 0;
  249.   int rc;
  250.  
  251.   for (y = cy; y > 0; y--)
  252.     {
  253.       if ((rc = BMP_readrow (fp, pixels[y-1], cx, bpp, col_min, col_max))%4)
  254.     return 0;
  255.       nbyte += rc;
  256.     }
  257.  
  258.   return nbyte;
  259. }
  260.  
  261. BOOL BMP_Decode (FILE *fp, UINT *x, UINT *y, INT *col_min, INT *col_max,
  262.          UCHAR ***cm, INT ***pixels)
  263. {
  264.   UCHAR c;
  265.   SHORT n, bpp;
  266.   UINT nbyte = 0, rc, len, off;
  267.   INT class;
  268.   INT cbfix, i;
  269.  
  270.   *col_max = 0;
  271.   *col_min = 256;
  272.  
  273.   nbyte += GetByte (fp, &c);  if (c != 'B')  return -1;
  274.   nbyte += GetByte (fp, &c);  if (c != 'M')  return -1;
  275.  
  276.   nbyte += GetLLong (fp, &len);
  277.   nbyte += SkipBytes (fp, 4);
  278.   nbyte += GetLLong (fp, &off);
  279.   nbyte += GetLLong (fp, &cbfix);
  280.  
  281.   if (cbfix == 12)
  282.     {
  283.       class = BMP_OS2;
  284.       nbyte += GetLShort (fp, &n);   *x = n;
  285.       nbyte += GetLShort (fp, &n);   *y = n;
  286.       nbyte += GetLShort (fp, &n);
  287.       nbyte += GetLShort (fp, &bpp);
  288.     }
  289.   else if (cbfix == 40)
  290.     {
  291.       class = BMP_WIN;
  292.       nbyte += GetLLong (fp, x);
  293.       nbyte += GetLLong (fp, y);
  294.       nbyte += GetLShort (fp, &n);
  295.       nbyte += GetLShort (fp, &bpp);
  296.       nbyte += SkipBytes (fp, 24);
  297.     }
  298.   else  return -1;
  299.  
  300.   if ((n != 1) || ((bpp != 1) && (bpp != 4) && (bpp != 8)))  return -1;
  301.  
  302.   if (!(*cm = malloc_uchar_matrix (3, (1 << bpp))))  return -1;
  303.  
  304.   for (i = 0; i < (1 << bpp); i++)
  305.     {
  306.       nbyte += GetByte (fp, &c);  (*cm)[2][i] = c;
  307.       nbyte += GetByte (fp, &c);  (*cm)[1][i] = c;
  308.       nbyte += GetByte (fp, &c);  (*cm)[0][i] = c;
  309.       if (cbfix == 40)  nbyte += SkipBytes (fp, 1);
  310.     }
  311.  
  312.   if (nbyte != BMP_offbits (class, bpp))  return -1;
  313.  
  314.   if (!(*pixels = malloc_int_matrix (*y, *x)))
  315.     {
  316.       free (*cm);
  317.       return -1;
  318.     }
  319.  
  320.   nbyte += BMP_readbits (fp, *x, *y, bpp, col_min, col_max, *pixels);
  321.  
  322.   if (nbyte != BMP_lenfile (class, bpp, *x, *y))
  323.     {
  324.       free (*cm);
  325.       free (*pixels);
  326.       return -1;
  327.     }
  328.  
  329.   return 0;
  330. }
  331.